import toml
import logging
from typing import Optional, Dict, Any
import os
import sys

logger = logging.getLogger(__name__)


class Config:
    """
    配置类，用于存储和访问应用程序的配置信息
    """

    def __init__(self, config_data: Dict[str, Any]):
        """
        初始化配置对象

        :param config_data: 从配置文件加载的原始配置数据
        """
        self._config_data = config_data

    def get(self, key_path: str, default: Any = None) -> Any:
        """
        根据键路径获取配置值

        :param key_path: 点分隔的键路径，例如 "email.host"
        :param default: 默认值，如果找不到键则返回此值
        :return: 配置值或默认值
        """
        keys = key_path.split('.')
        value = self._config_data

        try:
            for key in keys:
                value = value[key]
            return value
        except (KeyError, TypeError):
            return default

    def set(self, key_path: str, value: Any) -> None:
        """
        根据键路径设置配置值

        :param key_path: 点分隔的键路径，例如 "email.host"
        :param value: 要设置的值
        """
        keys = key_path.split('.')
        config_data = self._config_data

        # 遍历到倒数第二个键，确保路径存在
        for key in keys[:-1]:
            if key not in config_data:
                config_data[key] = {}
            config_data = config_data[key]

        # 设置最后一个键的值
        config_data[keys[-1]] = value

    def save(self, file_path: str) -> None:
        """
        保存配置到文件

        :param file_path: 配置文件路径
        """
        ConfigLoader.save_config(self._config_data, file_path)

    def get_email_config(self) -> Dict[str, Any]:
        """
        获取邮件配置
        优先级: notification > email
        """
        return {
            'enabled': self.get('notification.email_enabled', False),
            'host': self.get('notification.smtp_host', ''),
            'port': self.get('notification.smtp_port', ''),
            'username': self.get('notification.smtp_username', ''),
            'password': self.get('notification.smtp_password', ''),
            'use_tls': self.get('notification.use_tls', True),
            'recipients': [e.strip() for e in self.get('notification.email_recipient', '').split(',') if e.strip()]
        }

    def set_email_config(self, config: Dict[str, Any]):
        """
        保存邮件配置
        优先级: notification > email
        """
        self.set('notification.email_enabled', config['enabled'])
        self.set('notification.smtp_host', config['host'])
        self.set('notification.smtp_port', config['port'])
        self.set('notification.smtp_username', config['username'])
        self.set('notification.smtp_password', config['password'])
        self.set('notification.use_tls', config['use_tls'])
        self.set('notification.email_recipient', ','.join(config['recipients']))

    def get_audio_config(self) -> Dict[str, Any]:
        """
        获取音频配置
        优先级: notification > audio
        """
        notif_enabled = self.get('notification.audio_enabled')
        audio_enabled = self.get('audio.enabled', True)
        
        final_enabled = notif_enabled if notif_enabled is not None else audio_enabled

        return {
            'enabled': final_enabled,
            'sound_file': self.get('notification.audit_sound_file', ''),
            'default_file': None
        }


class ConfigLoader:
    """
    配置加载器，负责从文件加载配置并创建配置对象
    """

    @staticmethod
    def load_config(file_path: str) -> Config:
        """
        从指定路径加载配置文件

        :param file_path: 配置文件路径
        :return: 配置对象
        """
        try:
            with open(file_path, 'r', encoding='utf-8') as f:
                config_data = toml.load(f)
            logger.info(f"成功加载配置文件: {file_path}")
            return Config(config_data)
        except FileNotFoundError:
            logger.error(f"配置文件不存在： {file_path}")
            raise
        except Exception as e:
            logger.error(f"加载配置文件失败:{file_path}: {e}")
            raise

    @staticmethod
    def save_config(config_data: Dict[str, Any], file_path: str) -> None:
        """
        保存配置到文件

        :param config_data: 配置数据
        :param file_path: 配置文件路径
        """
        try:
            with open(file_path, 'w', encoding='utf-8') as f:
                toml.dump(config_data, f)
            logger.info(f"保存配置成功: {file_path}")
        except Exception as e:
            logger.error(f"保存配置失败: {file_path}: {e}")
            raise




# 全局配置对象
config: Optional[Config] = None


def load_global_config(config_file_path: str = "config/config.toml") -> Config:
    """
    加载全局配置对象

    :param config_file_path: 配置文件路径
    :return: 加载的配置对象
    """
    global config
    config = ConfigLoader.load_config(config_file_path)
    return config


def get_global_config() -> Optional[Config]:
    """
    获取全局配置对象

    :return: 全局配置对象
    """
    global config
    return config

def get_internal_resource_path(relative_path: str) -> str:
    """
    获取内部资源的绝对路径
    """
    if hasattr(sys, '_MEIPASS'):
        # PyInstaller bundled application
        resource_path = os.path.join(sys._MEIPASS, relative_path)
        if os.path.exists(resource_path):
            return resource_path
        else:
            logger.warning(f"Internal resource not found in _MEIPASS: {resource_path}. Falling back to current directory.")
            # Fallback to current directory for internal resources if not found in _MEIPASS
            # This is less ideal but might prevent immediate crashes for missing resources.
            # It's better to ensure resources are properly bundled with PyInstaller.
            return os.path.join(os.path.dirname(os.path.abspath(__file__)), relative_path)
    # Development environment
    return os.path.join(os.path.dirname(os.path.abspath(__file__)), relative_path)


def get_full_config_path(file_path: str = 'config/config.toml') -> str:
    """
    获取完整的配置文件路径
    优先查找外部配置文件（用户可修改），找不到则使用内部默认配置（打包进exe的）
    """
    config_file_name = os.path.basename(file_path)  # "config.toml"
    config_dir_name = os.path.dirname(file_path)    # "config"

    if getattr(sys, 'frozen', False):
        # 1. 查找外部配置文件 (用户可修改)
        base_path = os.path.dirname(sys.executable)

        # 尝试在 exe 同级目录下的 config 文件夹中查找 config.toml (例如: D:\dist\config\config.toml)
        external_config_sub = os.path.join(base_path, config_dir_name, config_file_name)
        if os.path.exists(external_config_sub):
            logger.info(f"Found external config at: {external_config_sub}")
            return external_config_sub

    else:
        # 开发环境
        base_path = os.path.dirname(os.path.abspath(__file__))
        file_p = os.path.join(base_path, file_path)
        logger.info(f"Found config in development environment at: {file_p}")
        return file_p

if __name__ == '__main__':
    # 加载配置
    config = load_global_config("config/config.toml")

    # 方式1: 使用通用get方法
    email_host = config.get("email.host")
    email_port = config.get("email.port")
    print("Email Host:", email_host)

    # 方式2: 使用专门的方法
    email_config = config.get_email_config()
    money_config = config.get_money_config()

    # 方式3: 使用全局配置对象
    global_config = get_global_config()
    email_host = global_config.get("email.host")
